package com.atguigu.tingshu.account.delay;

import com.atguigu.tingshu.account.mapper.UserAccountDetailMapper;
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.account.UserAccountDetail;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * title:
 * author: zgl
 * date: 2024/3/18
 * description：
 */
public class DelayUtil implements Delayed {

    private RedisTemplate redisTemplate;

    private UserAccountMapper userAccountMapper;

    private UserAccountDetailMapper detailMapper;

    private ExecutorService executorService;

    public DelayUtil(RedisTemplate redisTemplate, UserAccountMapper userAccountMapper, UserAccountDetailMapper detailMapper, ExecutorService executorService) {
        this.redisTemplate = redisTemplate;
        this.userAccountMapper = userAccountMapper;
        this.detailMapper = detailMapper;
        this.executorService = executorService;
    }

    private long timeout;

    private static final DelayQueue<DelayUtil> DELAY_QUEUE = new DelayQueue<>();

    //自旋 返回值<0 才会从延迟队列中出队
    @Override
    public long getDelay(TimeUnit unit) {
        return this.timeout - System.currentTimeMillis();
    }

    //队列排队方法
    @Override
    public int compareTo(Delayed o) {
        return (int) (this.timeout - ((DelayUtil) o).timeout);
    }

    //发送消息解锁账户
    public void sendUnlock(String orderNo, int delay, TimeUnit unit) {
        this.timeout = System.currentTimeMillis() + unit.toMillis(delay);
        //向延时队列发送消息
        DELAY_QUEUE.put(this);
        //线程池
        executorService.execute(() -> {
            try {
                DELAY_QUEUE.take();
                String key = "account:lock:prefix:";
                AccountLockResultVo resultVo = (AccountLockResultVo) this.redisTemplate.opsForValue().get(key + orderNo);
                if (resultVo == null) {
                    return;
                }
                //解锁
                //修改user_account表
                if (this.userAccountMapper.unlock(resultVo.getUserId(), resultVo.getAmount()) == 1) {
                    //新增user_account_detail表
                    UserAccountDetail accountDetail = new UserAccountDetail();
                    BeanUtils.copyProperties(resultVo, accountDetail);
                    accountDetail.setTradeType(SystemConstant.ACCOUNT_TRADE_TYPE_UNLOCK);
                    accountDetail.setTitle("账户解锁" + resultVo.getContent());
                    accountDetail.setOrderNo(orderNo);
                    this.detailMapper.insert(accountDetail);
                    //删除缓存
                    this.redisTemplate.delete(key + orderNo);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
